import { Context } from 'koa';
import { AppContext } from '@/types';
import { validate, commonSchemas } from '@/utils/validator';
import { success, paginated } from '@/utils/response';
import logger from '@/utils/logger';
import Joi from 'joi';
import Role from '@/models/Role.model';
import Permission from '@/models/Permission.model';
import RolePermission from '@/models/RolePermission.model';

interface CreateRoleData {
  name: string;
  description?: string;
  permissionIds?: string[];
}

interface ListRolesFilter {
  page?: number;
  pageSize?: number;
  search?: string;
}

interface UpdateRoleData {
  name?: string;
  description?: string;
}

interface AssignPermissionsData {
  permissionIds: string[];
}

/**
 * 角色管理控制器
 */
class RoleController {
  /**
   * 创建角色
   */
  async create(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;

    const schema = Joi.object({
      name: Joi.string().required().max(100).messages({
        'string.empty': '角色名称不能为空',
        'any.required': '角色名称是必填项',
      }),
      description: Joi.string().optional().allow(''),
      permissionIds: Joi.array().items(Joi.string().uuid()).optional(),
    });

    const data = await validate<CreateRoleData>(ctx.request.body as any, schema);

    try {
      // 创建角色
      const role = await Role.create({
        tenantId: user!.tenantId,
        name: data.name,
        description: data.description,
        isSystem: false,
      } as any);

      // 分配权限
      if (data.permissionIds && data.permissionIds.length > 0) {
        const rolePermissions = data.permissionIds.map((permissionId) => ({
          roleId: role.id,
          permissionId,
        }));
        await RolePermission.bulkCreate(rolePermissions as any);
      }

      logger.info(`角色创建成功: ${role.name} by ${user!.email}`);
      success(ctx, role, '角色创建成功');
    } catch (error) {
      logger.error('角色创建失败:', error);
      ctx.throw(500, '角色创建失败');
    }
  }

  /**
   * 获取角色列表
   */
  async list(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;

    const schema = Joi.object({
      page: commonSchemas.page,
      pageSize: commonSchemas.pageSize,
      search: Joi.string().optional().allow(''),
    });

    const filter = await validate<ListRolesFilter>(ctx.query as any, schema);
    const page = filter.page || 1;
    const pageSize = filter.pageSize || 20;

    try {
      const where: any = {};

      // 超级管理员可以看到所有角色
      // 普通用户只能看到系统角色（tenantId为null）和自己租户的角色
      if (user!.type !== 'super_admin') {
        const { Op } = await import('sequelize');
        where[Op.or] = [
          { tenantId: null }, // 系统角色
          { tenantId: user!.tenantId }, // 自己租户的角色
        ];
      }

      if (filter.search) {
        where.name = { $like: `%${filter.search}%` };
      }

      const { rows: roles, count: total } = await Role.findAndCountAll({
        where,
        limit: pageSize,
        offset: (page - 1) * pageSize,
        order: [['createdAt', 'DESC']],
      });

      paginated(ctx, roles, total, page, pageSize);
    } catch (error) {
      logger.error('获取角色列表失败:', error);
      ctx.throw(500, '获取角色列表失败');
    }
  }

  /**
   * 获取角色详情
   */
  async detail(ctx: Context) {
    const { id } = ctx.params;

    try {
      const role = await Role.findByPk(id);

      if (!role) {
        ctx.throw(404, '角色不存在');
      }

      // 获取角色的权限
      const rolePermissions = await RolePermission.findAll({
        where: { roleId: role.id },
      });

      const permissionIds = rolePermissions.map((rp: any) => rp.permissionId);
      const permissions = await Permission.findAll({
        where: { id: permissionIds },
      });

      const result = {
        ...role.toJSON(),
        permissions,
      };
      success(ctx, result);
    } catch (error) {
      logger.error('获取角色详情失败:', error);
      ctx.throw(500, '获取角色详情失败');
    }
  }

  /**
   * 更新角色
   */
  async update(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;
    const { id } = ctx.params;

    const schema = Joi.object({
      name: Joi.string().optional().max(100),
      description: Joi.string().optional().allow(''),
    });

    const data = await validate<UpdateRoleData>(ctx.request.body as any, schema);

    try {
      const role = await Role.findByPk(id);

      if (!role) {
        ctx.throw(404, '角色不存在');
      }

      if (role.isSystem) {
        ctx.throw(403, '系统角色不允许修改');
      }

      await role.update(data as any);

      logger.info(`角色更新成功: ${role.name} by ${user!.email}`);
      success(ctx, role, '角色更新成功');
    } catch (error) {
      logger.error('角色更新失败:', error);
      ctx.throw(500, '角色更新失败');
    }
  }

  /**
   * 删除角色
   */
  async delete(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;
    const { id } = ctx.params;

    try {
      const role = await Role.findByPk(id);

      if (!role) {
        ctx.throw(404, '角色不存在');
      }

      if (role.isSystem) {
        ctx.throw(403, '系统角色不允许删除');
      }

      // 检查是否有用户使用此角色
      const User = (await import('@/models/User.model')).default;
      const userCount = await User.count({
        where: { roleId: id },
      });

      if (userCount > 0) {
        ctx.throw(400, `该角色下还有 ${userCount} 个用户，无法删除`);
      }

      await role.destroy();

      logger.info(`角色删除成功: ${role.name} by ${user!.email}`);
      success(ctx, null, '角色删除成功');
    } catch (error) {
      logger.error('角色删除失败:', error);
      ctx.throw(500, '角色删除失败');
    }
  }

  /**
   * 获取角色权限
   */
  async getPermissions(ctx: Context) {
    const { id } = ctx.params;

    try {
      const role = await Role.findByPk(id);

      if (!role) {
        ctx.throw(404, '角色不存在');
      }

      // 查询角色的权限ID列表
      const rolePermissions = await RolePermission.findAll({
        where: { roleId: id },
        attributes: ['permissionId'],
      });

      const permissionIds = rolePermissions.map((rp) => rp.permissionId);

      success(ctx, permissionIds, '获取权限成功');
    } catch (error) {
      logger.error('获取角色权限失败:', error);
      ctx.throw(500, '获取角色权限失败');
    }
  }

  /**
   * 分配权限
   */
  async assignPermissions(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;
    const { id } = ctx.params;

    const schema = Joi.object({
      permissionIds: Joi.array().items(Joi.string().uuid()).min(0).required(),
    });

    const data = await validate<AssignPermissionsData>(ctx.request.body as any, schema);

    try {
      const role = await Role.findByPk(id);

      if (!role) {
        ctx.throw(404, '角色不存在');
      }

      if (role.isSystem) {
        ctx.throw(403, '系统角色不允许修改权限');
      }

      // 多租户权限检查：非超管只能管理自己租户的角色
      if (user!.type !== 'super_admin') {
        if (!role.tenantId || role.tenantId !== user!.tenantId) {
          ctx.throw(403, '无权限操作该角色');
        }
      }

      // 验证权限ID是否有效
      if (data.permissionIds.length > 0) {
        const Permission = (await import('@/models/Permission.model')).default;
        const permissions = await Permission.findAll({
          where: { id: data.permissionIds },
        });

        if (permissions.length !== data.permissionIds.length) {
          ctx.throw(400, '包含无效的权限ID');
        }
      }

      // 删除现有权限
      await RolePermission.destroy({
        where: { roleId: id },
      });

      // 添加新权限
      if (data.permissionIds.length > 0) {
        const rolePermissions = data.permissionIds.map((permissionId) => ({
          roleId: id,
          permissionId,
        }));
        await RolePermission.bulkCreate(rolePermissions as any);
      }

      logger.info(`角色权限分配成功: ${role.name} by ${user!.email}`);
      success(ctx, null, '权限分配成功');
    } catch (error) {
      logger.error('权限分配失败:', error);
      ctx.throw(500, '权限分配失败');
    }
  }
}

export default new RoleController();

